﻿using Engine;
using Game.NetWork.Packages;
using Game.NetWork;
using Game.Server.Event;
using Game.Server.PlayerEvent;
using System.Text;

namespace Game.Server.Plugins
{
    public class CmdInvincible : AbstractProcessCmd
    {
        public override string Cmd => "inv";

        public override string Introduce => "/inv  -查看锁血与加血指令帮助";

        public override int AuthLevel => 100;

        public override DisplayType Display => DisplayType.All;

        public override void ProcessCmd()
        {
            if (GameManager.Project == null) return;
            if (m_messageDatas.Length >= 2)
            {
                if (m_isTerminal == true)
                {
                    SendMessage(Cmd, "控制台不能使用");
                    return;
                }
                try
                {
                    if (m_messageDatas[1] == "lock")
                    {
                        bool flag = m_client.PlayerData.ComponentPlayer.ComponentHealth.IsInvulnerable;
                        m_client.PlayerData.ComponentPlayer.ComponentHealth.IsInvulnerable = !flag;
                        SendMessage(Cmd, "已成功" + (!flag ? "开启锁血模式": "关闭锁血模式"));
                    }
                    else if(m_messageDatas[1] == "heal")
                    {
                        m_client.PlayerData.ComponentPlayer.ComponentHealth.Heal(1f);
                        CommonLib.Net.QueuePackage(new ComponentHealthPackage(m_client.PlayerData.ComponentPlayer.ComponentHealth));
                        ComponentFlu componentFlu = m_client.PlayerData.ComponentPlayer.Entity.FindComponent<ComponentFlu>();
                        componentFlu.m_fluOnset = 0f;
                        componentFlu.m_fluDuration = 0f;
                        componentFlu.m_coughDuration = 0f;
                        componentFlu.m_blackoutDuration = 0f;
                        SendMessage(Cmd, "已成功回满血");
                    }
                    else
                    {
                        SendMessage(Cmd, "输入的指令有误，请重试");
                    }
                }
                catch
                {
                    SendMessage(Cmd, "输入的指令有误，请重试");
                }
            }
            else
            {
                SendMessage(Cmd, "/inv lock  -锁血\n/inv heal  -回血");
            }
        }
    }

    public class ExTpZHPlugin : ServerPlugin, IPlayerInteractEventHandle
    {
        public override int Version => 10000;

        public override string Name => "经验球飞雷神插件";

        public byte FirstLevel => 0;

        public override void Initialize()
        {
            PlayerInteractEventManager.AddObject(this);
        }

        public bool Use(ComponentPlayer componentPlayer, object raycast, int activeBlockValue)
        {
            return true;
        }

        public bool Interact(ComponentPlayer componentPlayer, CellFace cellFace)
        {
            return true;
        }

        public bool Hit(ComponentPlayer componentPlayer, ComponentBody componentBody, Vector3 hitPoint, Vector3 hitDirection)
        {
            return true;
        }

        public bool Aim(ComponentPlayer componentPlayer, int activeBlockValue, Ray3 aim, AimState state)
        {
            if (Terrain.ExtractContents(activeBlockValue) == 248 && componentPlayer.PlayerData.ServerManager)
            {
                if (state == AimState.Completed)
                {
                    object result = Raycast(aim, componentPlayer.ComponentMiner);
                    if (result is TerrainRaycastResult)
                    {
                        CellFace cellFace = ((TerrainRaycastResult)result).CellFace;
                        componentPlayer.ComponentBody.Position = new Vector3(cellFace.Point) + new Vector3(0.5f) - aim.Direction * 2f;
                        CommonLib.Net.QueuePackage(new ComponentPlayerPackage(componentPlayer, ComponentPlayerPackage.PlayerAction.PositionSet));
                    }
                    else if (result is BodyRaycastResult)
                    {
                        ComponentBody componentBody = ((BodyRaycastResult)result).ComponentBody;
                        componentPlayer.ComponentBody.Position = componentBody.Position - aim.Direction * 2f;
                        CommonLib.Net.QueuePackage(new ComponentPlayerPackage(componentPlayer, ComponentPlayerPackage.PlayerAction.PositionSet));
                    }
                }
            }
            return true;
        }

        public static object Raycast(Ray3 ray, ComponentMiner componentMiner)
        {
            float reach = 1000f;
            Vector3 creaturePosition = componentMiner.ComponentCreature.ComponentCreatureModel.EyePosition;
            Vector3 start = ray.Position;
            var direction = Vector3.Normalize(ray.Direction);
            Vector3 end = ray.Position + direction * 500f;
            Point3 startCell = Terrain.ToCell(start);
            BodyRaycastResult? bodyRaycastResult = componentMiner.m_subsystemBodies.Raycast(start, end, 0.35f, (ComponentBody body, float distance) =>
            {
                bool flag = Vector3.DistanceSquared(start + distance * direction, creaturePosition) <= reach * reach;
                bool flag2 = body.Entity != componentMiner.Entity && !body.IsChildOfBody(componentMiner.ComponentCreature.ComponentBody) && !componentMiner.ComponentCreature.ComponentBody.IsChildOfBody(body);
                bool flag3 = Vector3.Dot(Vector3.Normalize(body.BoundingBox.Center() - start), direction) > 0.7f;
                return (flag && flag2 && flag3) ? true : false;
            });
            MovingBlocksRaycastResult? movingBlocksRaycastResult = componentMiner.m_subsystemMovingBlocks.Raycast(start, end, extendToFillCells: true);
            TerrainRaycastResult? terrainRaycastResult = componentMiner.m_subsystemTerrain.Raycast(start, end, useInteractionBoxes: true, skipAirBlocks: true, delegate (int value, float distance)
            {
                return true;
            });
            float num = bodyRaycastResult.HasValue ? bodyRaycastResult.Value.Distance : float.PositiveInfinity;
            float num2 = movingBlocksRaycastResult.HasValue ? movingBlocksRaycastResult.Value.Distance : float.PositiveInfinity;
            float num3 = terrainRaycastResult.HasValue ? terrainRaycastResult.Value.Distance : float.PositiveInfinity;
            if (num < num2 && num < num3)
            {
                return bodyRaycastResult.Value;
            }
            if (num2 < num && num2 < num3)
            {
                return movingBlocksRaycastResult.Value;
            }
            if (num3 < num && num3 < num2)
            {
                return terrainRaycastResult.Value;
            }
            return new Ray3(start, direction);
        }

        public override void Load()
        {
            BlocksManager.Blocks[248].MaxStacking = 100000000;
            BlocksManager.Blocks[248].ProjectileSpeed = 1000000f;
        }

        public override void Save()
        {
        }

        /// <summary>
        /// 给指定玩家发送提示
        /// </summary>
        /// <param name="componentPlayer"></param>
        /// <param name="text"></param>
        public void DisplaySmallMessageNet(ComponentPlayer componentPlayer, string text)
        {
            var messagePackget = new MessagePackage(null, text, 0, null);
            messagePackget.To = componentPlayer.PlayerData.Client;
            CommonLib.Net.QueuePackage(messagePackget);
        }
    }
}